package com.google.code.tretris.server;

import java.util.ArrayList;
import java.util.Random;

import android.util.Log;

import com.google.code.tretris.common.Tetromino;
import com.google.code.tretris.events.MoveEvent;

public class GamePlayer {
	private final String clientID;
	private GameBoard gameboard;
	private ActiveTetromino activeTetromino;
	private Random random = new Random();
	private static Tetromino[] spawn = { Tetromino.I, Tetromino.J, Tetromino.L,
			Tetromino.O, Tetromino.S, Tetromino.T, Tetromino.Z };
	private ArrayList<MoveEvent> eventbuffer = new ArrayList<MoveEvent>();

	private boolean inplay = true;
	private boolean activehasmoved = false;

	public GamePlayer(final String clientID) {
		this.clientID = clientID;
		gameboard = new GameBoard();
		spawn() ;
	}

	public void pushEvent(MoveEvent event) {
		eventbuffer.add(event);
	}

	public void spawn() {
		activeTetromino = new ActiveTetromino(spawn[random.nextInt(7)]);
		Log.d("GamePlayer", "Client " + getClientID() + " spawned a new tetromino: " + activeTetromino);
		activehasmoved = false;
	}

	public boolean isInplay() {
		return inplay;
	}

	public void setInplay(boolean inplay) {
		this.inplay = inplay;
	}

	public String getClientID() {
		return clientID;
	}

	public void heartbeat() {
		Log.d("GamePlayer", "Heartbeat: Client " + getClientID() + " activeTetromino " + activeTetromino);
		int proposedY = activeTetromino.getY();
		boolean reduce = false;
		// Apply gravity
		proposedY++;
		if (!gameboard.canPlace(activeTetromino.getTetromino(), activeTetromino
				.getX(), proposedY, activeTetromino.getRotation())) {
			proposedY--;
			reduce = true;
		}

		int accumulatedX = activeTetromino.getX();
		int accumulatedrotation = activeTetromino.getRotation();
		// Apply events
		for (MoveEvent event : eventbuffer) {
			Log.d("GamePlayer", "Client " + getClientID() + " processing " + event.toString());

			int proposedX = accumulatedX + event.getDeltax();
			int proposedrotation = accumulatedrotation
					+ event.getRotationchange();
			if (proposedrotation < 0) {
				proposedrotation = 3;
			} else if (proposedrotation > 3) {
				proposedrotation = 0;
			}
			if (gameboard.canPlace(activeTetromino.getTetromino(), proposedX,
					proposedY, proposedrotation)) {
				accumulatedrotation = proposedrotation;
				accumulatedX = proposedX;
			}
		}

		eventbuffer.clear();

		if (reduce) {
			Log.d("GamePlayer", "Client " + getClientID() + " reduce Tetromino "
					+ activeTetromino.getTetromino().letter);
			gameboard.reduce(activeTetromino.getTetromino(), accumulatedX,
					proposedY, accumulatedrotation);
			if (activehasmoved) {
				spawn();
			} else {
				Log.d("GamePlayer", "Client " + getClientID()
						+ " became out of play");
				setInplay(false);
			}
		} else {
			activeTetromino.setRotation(accumulatedrotation);
			activeTetromino.setX(accumulatedX);
			activeTetromino.setY(proposedY);
			activehasmoved = true;
		}
	}

	public GameBoard getGameboard() {
		return gameboard;
	}

	public ActiveTetromino getActiveTetromino() {
		return activeTetromino;
	}
	
}
